package com.example.ws;


import com.example.controller.WebSocketController;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 本来用来演示:
 *
 * @author success
 */
@Slf4j
@Component
@ServerEndpoint(value = "/tt/{id}")
public class WebSocketProcess {
    /*
     * 持有每个webSocket对象，以key-value存储到线程安全ConcurrentHashMap，
     */
    private static ConcurrentHashMap<Long, WebSocketProcess> concurrentHashMap = new ConcurrentHashMap<>(12);

    /**
     * 会话对象
     **/
    private Session session;

    @Bean
    private WebSocketController wsc(){
        return new WebSocketController();
    }


    /*
     * 客户端创建连接时触发
     * */
    @OnOpen
    public void onOpen(Session session, @PathParam("id") long id) {
        //每新建立一个连接，就把当前客户id为key,this为value存储到map中
        this.session = session;
        concurrentHashMap.put(id, this);
        System.out.println(id+"建立连接");
        log.info("Open a websocket. id={}", id);
    }

    /**
     * 客户端连接关闭时触发
     **/
    @OnClose
    public void onClose(Session session, @PathParam("id") long id) {
        //客户端连接关闭时，移除map中存储的键值对
        concurrentHashMap.remove(id);
        System.out.println("关闭连接"+id);
        log.info("close a websocket, concurrentHashMap remove sessionId= {}", id);
    }

    /**
     * 接收到客户端消息时触发
     */
    @OnMessage
    public void onMessage(String message, @PathParam("id") String id) throws Exception {
        log.info("receive a message from client id={},msg={}", id, message);
        //模拟群发的功能
//        sendAllMessage(message);
        Long sid = Long.valueOf(message.split("\\|")[0]);
        String ms = message.split("\\|")[1];
        Long usid = Long.valueOf(id);
        System.out.println("共有"+concurrentHashMap+"连接");
        String us = message.split("\\|")[2];
        int b=0;
        for (int i=0;i<message.length();i++){
            if (message.charAt(i) == '|'){
                b++;
                System.out.println("<-=->");
                System.out.println(b);
            }
        }
        Integer posId = null;
        if (b==3){
            posId = Integer.valueOf(message.split("\\|")[3]);
        }
        if (us.equals("jr")){
            wsc().addWS(sid.intValue(), usid.intValue(),ms,1,posId);
        } else if (us.equals("js")){
            wsc().addWS(usid.intValue(),sid.intValue(),ms,0,posId);
        }

        //单发功能
        for (Long uid : concurrentHashMap.keySet()) {
            if (sid.equals(uid) || usid.equals(uid)){
                sendMessage(usid,uid,ms);
            }
        }


    }

    /**
     * 连接发生异常时候触发
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("Error while websocket. ", error);
    }

    /**
     * 发送消息到指定客户端
     *  @param id
     *  @param message
     * */
    public void sendMessage(Long usid,long id, String message) throws Exception {
        //根据id,从map中获取存储的webSocket对象
        WebSocketProcess webSocketProcess = concurrentHashMap.get(id);
        if (!ObjectUtils.isEmpty(webSocketProcess)) {
            //当客户端是Open状态时，才能发送消息
            if (webSocketProcess.session.isOpen()) {
                System.out.println("客户端"+id+"开启:"+message);
                System.out.println("发送给"+usid+"==>");
                System.out.println(concurrentHashMap);
                webSocketProcess.session.getBasicRemote().sendText(usid+"|"+message);
            } else {
                System.out.println("客户端"+id+"未开启");
                webSocketProcess.session.getBasicRemote().sendText(usid+"|"+message);
                log.error("websocket session={} is closed ", id);
            }
        } else {
            log.error("websocket session={} is not exit ", id);
        }
    }

    /**
     * 发送消息到所有客户端
     *
     * */
    public void sendAllMessage(String msg) throws Exception {
        log.info("online client count={}", concurrentHashMap.size());
        Set<Map.Entry<Long, WebSocketProcess>> entries = concurrentHashMap.entrySet();
        for (Map.Entry<Long, WebSocketProcess> entry : entries) {
            Long cid = entry.getKey();
            WebSocketProcess webSocketProcess = entry.getValue();
            boolean sessionOpen = webSocketProcess.session.isOpen();
            if (sessionOpen) {
                webSocketProcess.session.getBasicRemote().sendText(msg);
            } else {
                log.info("cid={} is closed,ignore send text", cid);
            }
        }
    }
}
